// 与pos机相关的逻辑
package oauth

import (
	"context"
	"fmt"
	"micro-oauth/datamodels/autherror"
	"micro-oauth/config"
	model "micro-oauth/datamodels"
	"micro-oauth/datamodels/enum"
	"micro-oauth/utils"
	"time"
)

func (s *OauthServiceImpl) getPosUser(ctx context.Context, client *model.Client) (*model.User, autherror.HexError) {
	posUser := s.repoService.GetUserByName(client.PartnerId, client.ScopeId, "pos")
	if posUser == nil {
		posUser = &model.User{
			PartnerId: client.PartnerId,
			ScopeId:   client.ScopeId,
			Name:      "pos",
			Code:      "pos",
			Remark:    "clientId: " + client.ClientId,
		}
		err := s.repoService.AddUser(posUser)
		if err != nil {
			return nil, autherror.DBError(err.Error())
		}
	}
	return posUser, nil
}

func (s *OauthServiceImpl) IssuePosToken(ctx context.Context, clientId, clientSecret string) (*model.Token, autherror.HexError) {
	posClient := s.repoService.GetClientById(clientId)
	fmt.Println("posClient",posClient)
	if posClient == nil {
		return nil, autherror.NotFound("can not find pos client")
	}
	if posClient.Secret != clientSecret {
		return nil, autherror.InvalidData("wrong pos client secret")
	}
	if posClient.Type != enum.PosClient {
		return nil, autherror.InvalidData("wrong pos client type")
	}
	posUser, hexErr := s.getPosUser(ctx, posClient)
	if hexErr != nil {
		return nil, hexErr
	}
	if err := s.clearUserToken(ctx, posUser, true); err != nil {
		return nil, err
	}
	device := new(model.Device)
	tokenObj, hexErr := s.genBearerTokenForUser(posClient, posUser, "", "hex-server", device)
	if hexErr != nil {
		return nil, hexErr
	}
	return tokenObj, nil
}

func (s *OauthServiceImpl) CreateOrGetPosClient(ctx context.Context, req *model.CreatePosClientRequest) (*model.Client, autherror.HexError) {
	if req.TerminalId == 0 {
		return nil, autherror.InvalidData("terminal_id must not be zero")
	}
	client := s.repoService.GetPosClientByTerminalId(req.TerminalId)
	if client != nil {
		return client, nil
	}
	salt := fmt.Sprintf("%d-%d", req.TerminalId, req.ScopeId)
	clientId := utils.GenUniqueToken("client_id-" + salt)
	clientSecret := utils.GenUniqueToken("client_secret-" + salt)
	client = &model.Client{
		PartnerId:           req.PartnerId,
		ClientId:            clientId,
		Secret:              clientSecret,
		TerminalId:          req.TerminalId,
		ScopeId:             req.ScopeId,
		Type:                enum.PosClient,
		TokenExpireDuration: config.PosTokenLifetime.Nanoseconds() / int64(time.Second),
		ScopeCodes:          "hex-server",
	}
	scopeDao := s.repoService.GetScopeById(req.ScopeId)
	if scopeDao == nil {
		return nil, autherror.NotFound("can not found scope")
	}
	if scopeDao.PartnerId != req.PartnerId {
		return nil, autherror.InvalidData("scope and partner not match")
	}

	err := s.repoService.AddClient(client)
	if err != nil {
		return nil, autherror.DBError(err.Error())
	}
	return client, nil
}
